﻿#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<vector>
#include<list>
#include<string>
using namespace std;

//多态

//实现多态还有两个必须重要条件：
//• 必须是基类的指针或者引⽤调⽤虚函数
//• 被调⽤的函数必须是虚函数，并且完成了虚函数重写 / 覆盖。
//virtual只有成员函数和基类才有意义
//class Person
//{
//public:
//	virtual void buyticket()
//	{
//		cout << "买票——全价" << endl;
//	}
//};
//
//class Student : public Person
//{
//public:
//	virtual void buyticket()
//	{
//		cout << "买票——打折" << endl;
//	}
//};
//
////指针类型
//void func(Person* p)//基类的指针
//{
//	p->buyticket();
//}
//
////void func(Student* s)
////{
////	s->buyticket();
////}
//
////引用也可以用
//void func(Person& p)//基类的引用
//{
//	p.buyticket();
//}
//
//int main()
//{
//	Person p;
//	Student s;
//	func(&p);
//	func(&s);
//
//	Person p;
//	Student s;
//	func(p);
//	func(s);
//
//	return 0;
//}


//虚函数的作用是：在构成多态时重写虚函数的实现，也就是用基类虚函数的声明+派生类重写的虚函数实现

//class A
//{
//public:
//	virtual void func(int val = 1) { std::cout << "A->" << val << std::endl; }
//	virtual void test() { func(); }
//};
//
//class B : public A
//{
//public:
//	void func(int val = 0) { std::cout << "B->" << val << std::endl; }
//};
//
//int main(int argc, char* argv[])
//{
//	B* p = new B;
//	p->test();
//	p->func();
//	return 0;
//}

//virtual void func(int val = 1) { std::cout << "B->" << val << std::endl; }
//实际函数实现



//协变
//class A {};
//class B : public A {};
//
//class Person {
//public:
//	virtual A* BuyTicket()//A改写成基类名也是正确的
//	{
//		cout << "买票-全价" << endl;
//		return nullptr;
//	}
//};
//
//class Student : public Person {
//public:
//	virtual B* BuyTicket()//B改写成派生类名也是正确的
//	{
//		cout << "买票-打折" << endl;
//		return nullptr;
//	}
//};
//
//void Func(Person* ptr)
//{
//	ptr->BuyTicket();
//}
//
//int main()
//{
//	Person ps;
//	Student st;
//	Func(&ps);
//	Func(&st);
//	return 0;
//}



//虚函数的重写
//多态调用，指向谁，调用谁的析构函数
// 
// delete
//p1->析构函数()跟指向的类型有关 + operator delete(p1)

// 由于多态的调用,虚函数的名称必须相同，所以析构函数都改名为destructor(),也就是构成了隐藏.。
// 如果不正常调用则会出现有的函数未进行析构，就会导致内存泄露。
//p1->destructor()


//class A
//{
//public:
//	virtual ~A()
//	{
//		cout << "~A()" << endl;
//	}
//};
//
//class B : public A {
//public:
//	virtual ~B()//派生类可以不加virtual，但最好还是加上
//	{
//		cout << "~B()->delete:" << _p << endl;
//		delete _p;
//	}
//protected:
//	int* _p = new int[10];
//};
////  只有派⽣类Student的析构函数重写了Person的析构函数，下⾯的delete对象调⽤析构函数，才能
////	构成多态，才能保证p1和p2指向的对象正确的调⽤析构函数。
//int main()
//{
//	A* p1 = new A;
//	A* p2 = new B;
//	delete p1;
//	delete p2;
//	return 0;
//}



//纯虚函数和抽象类

//class Car//抽象类
//{
//public:
//
//	//1、抽象类不能实例化对象
//	//2、强制子类重写
//	virtual void Drive() = 0;//纯虚函数
//};
//
//
//class Benz :public Car
//{
//public:
//	virtual void Drive()
//	{
//		cout << "Benz-舒适" << endl;
//	}
//};
//
//
//class BMW :public Car
//{
//public:
//	virtual void Drive()
//	{
//		cout << "BMW-操控" << endl;
//	}
//};
//
//
//int main()
//{
//	// 编译报错：error C2259: “Car”: ⽆法实例化抽象类 
//	//Car car;
//	Car* pBenz = new Benz;
//	pBenz->Drive();
//	Car* pBMW = new BMW;
//	pBMW->Drive();
//	return 0;
//}



//小插曲

//void func(int i);
//void func(double d);
//
//int main()
//{
//	int i;
//	double d;
//	cin >> i;
//	cin >> d;
//	func(i);
//	func(d);
//	return 0;
//}


//动态的多态

//虚函数表,简称虚表，本质上是一个函数指针数组
//虚函数表指针
//class Base
//{
//public:
//	virtual void Func1()
//	{
//		cout << "Func1()" << endl;
//	}
//protected:
//	int _b = 1;
//	char _ch = 'x';
//};
//
//int main()
//{
//	Base b;
//	cout << sizeof(b) << endl;
//	return 0;
//}

//本质是运行时，指向哪个对象就去这个对象的虚函数表中找到对应的虚函数地址进行调用






//满足多态，运行时到指向对象虚函数表中找到对应的虚函数调用
//不满足多态，编译链接时就确定函数的地址

//class Person
//{
//public:
//	virtual void buyticket()
//	{
//		cout << "买票——全价" << endl;
//	}
//};
//
//class Student : public Person
//{
//public:
//	virtual void buyticket()
//	{
//		cout << "买票——半价" << endl;
//	}
//};
//
//class Soilder : public Person
//{
//public:
//	virtual void buyticket()
//	{
//		cout << "买票——优先" << endl;
//	}
//};
//
//void func(Person* p)
//{
//	p->buyticket();
//}
//
//int main()
//{
//	Person p;
//	Student s;
//	Soilder sr;
//	func(&p);
//	func(&s);
//	func(&sr);
//	return 0;
//}


//虚函数表


class Person
{
public:
	virtual void Func1(){}
	void Func2(){}

};

class Student : public Person
{
public:
	virtual void Func1() {}
	void Func2() {}

};

int main()
{
	int i = 0;
	static int j = 1;
	int* p1 = new int;
	const char* p2 = "xxxxxxxx";
	printf("栈:%p\n", &i);
	printf("静态区:%p\n", &j);
	printf("堆:%p\n", p1);
	printf("常量区:%p\n", p2);
	
	Person p;
	Person* ptr = &p;
	Student s;


	printf("Person虚表地址:%p\n", *((int*)ptr));
	printf("Student虚表地址:%p\n", *((int*)&s));
	printf("虚函数地址:%p\n", &Person::Func1);
	printf("普通函数地址:%p\n", &Person::Func2);

	return 0;
}
